﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.LIB;
using YArchitech.ProgressBar;
using YArchitech.Revit;
using YJKRevitBase.WinForm;
using YJKRevitBase.XmlUtility;
using YJKRevitKernel.ElementSearchUtility;
using YJKRevitKernel.RevitInteractiveUtility;

namespace YJKInspectModel.ModelValidation.ClearHeightCheck
{
	public class ClearHeightCheckFun
	{
		public ClearHeightCheckFun(UIApplication app)
		{
			this.m_UiApp = app;
			this.m_uiDoc = app.ActiveUIDocument;
			this.m_doc = this.m_uiDoc.Document;
			this.m_allLinkDocs = ClearHeightCheckFun.GetLinkDocs(this.m_doc);
		}

		public ClearHeightCheckFun(Autodesk.Revit.DB.Document doc)
		{
			this.m_doc = doc;
			this.m_allLinkDocs = ClearHeightCheckFun.GetLinkDocs(this.m_doc);
		}

		public void setZoomElement(Element element)
		{
			this.m_ZoomElement = element;
		}

		public List<Element> getAllElements()
		{
			ElementFilter elementFilter = new ElementClassFilter(typeof(FamilyInstance));
			ElementClassFilter elementClassFilter = new ElementClassFilter(typeof(HostObject));
			LogicalOrFilter logicalOrFilter = new LogicalOrFilter(elementFilter, elementClassFilter);
			List<Element> list = new List<Element>();
			list = new FilteredElementCollector(this.m_doc).WherePasses(logicalOrFilter).ToList<Element>();
			foreach (Autodesk.Revit.DB.Document document in this.m_allLinkDocs)
			{
				if (document != null)
				{
					List<Element> collection = new FilteredElementCollector(document).WherePasses(logicalOrFilter).ToList<Element>();
					list.AddRange(collection);
				}
			}
			return list;
		}

		public void ZoomElement()
		{
			ElementsZoomUtility.ZoomElement3d(this.m_uiDoc, this.m_ZoomElement, true, false, null);
		}

		public List<ElementId> SelectElement()
		{
			List<ElementId> result = new List<ElementId>();
			RevitVersionFuncs.ClearSelection(this.m_uiDoc.Selection);
			List<Reference> list = this.m_uiDoc.Selection.PickObjects((Autodesk.Revit.UI.Selection.ObjectType)1, "请选择要定位的实例!").ToList<Reference>();
			if (list.Count == 0)
			{
				YJKMessageBox.Show("未选中任何实例，请重新选择。");
				return result;
			}
			return (from pickObj in list
			select pickObj.ElementId).ToList<ElementId>();
		}

		public void CreateClearHeightPlan()
		{
			bool flag = true;
			bool flag2 = true;
			FillFatternType type;
			this.getFillType(ref flag, ref flag2, out type);
			this.m_SpaceHeight = 10000.0;
			this.CheckBySelectRegion(false);
			if (this.m_ClearHeightInLevels.Count < 1)
			{
				return;
			}
			Dictionary<int, ElementId> dictionary = new Dictionary<int, ElementId>();
			List<FillPatternStruc> fillPatternList = new List<FillPatternStruc>();
			fillPatternList = FillPatternManage.GetFillPatternData(this.m_doc, type);
			string str = "";
			bool flag3 = false;
			foreach (Level key in this.m_ClearHeightInLevels.Keys)
			{
				foreach (ClearHeightArea clearHeightArea in this.m_ClearHeightInLevels[key])
				{
					List<CurveLoop> curveLoop = clearHeightArea.GetCurveLoop();
					double minClearHeight = clearHeightArea.GetMinClearHeight();
					if (minClearHeight < 0.0)
					{
						str = "检查区域内没有需要检查的设备";
					}
					else
					{
						bool isVisible;
						ElementId fillPatternId = this.GetFillPatternId(fillPatternList, minClearHeight, out isVisible);
						if (fillPatternId == null)
						{
							str = "净高对应的区域填充模板为空";
						}
						else
						{
							Transaction transaction = new Transaction(this.m_doc, "createfillplan");
							transaction.Start();
							try
							{
								FilledRegion filledRegion = this.CreatefilledRegion(fillPatternId, curveLoop, isVisible);
								if (filledRegion == null)
								{
									transaction.RollBack();
								}
								else
								{
									flag3 = true;
									this.m_doc.Regenerate();
									BoundingBoxXYZ boundingBoxXYZ = filledRegion.get_BoundingBox(this.m_doc.ActiveView);
									XYZ position = (boundingBoxXYZ.Max + boundingBoxXYZ.Min) / 2.0;
									int num = (int)(minClearHeight + 0.5);
									string stext = num.ToString();
									ElementId textId = null;
									if (flag)
									{
										textId = this.CreateTextNote(stext, position).Id;
									}
									this.SetFillReginParameters(filledRegion, textId, 1);
									bool flag4 = false;
									using (Dictionary<int, ElementId>.KeyCollection.Enumerator enumerator3 = dictionary.Keys.GetEnumerator())
									{
										while (enumerator3.MoveNext())
										{
											if (enumerator3.Current == num)
											{
												flag4 = true;
												break;
											}
										}
									}
									if (!flag4)
									{
										dictionary.Add(num, fillPatternId);
									}
									transaction.Commit();
								}
							}
							catch (Exception)
							{
								flag2 = false;
								transaction.RollBack();
							}
						}
					}
				}
			}
			if (!flag3)
			{
				YJKMessageBox.Show("创建净高区域失败！" + str);
				return;
			}
			if (flag2)
			{
				this.CreateFillLegent(dictionary);
			}
		}

		private void getFillType(ref bool isText, ref bool islegent, out FillFatternType fillFatternType)
		{
			fillFatternType = FillFatternType.Pattern;
			YJKRevitBase.XmlUtility.XmlHelper xmlHelper = new YJKRevitBase.XmlUtility.XmlHelper();
			string xmlPath = Path.Combine(Product.WorkingLocation, "ClearHeightSetForm.xml");
			xmlHelper.LoadXml(xmlPath, "Root");
			xmlHelper.SelectNode(Path.Combine("Root", "ClearHeightSetForm", "Params"));
			if (!xmlHelper.GetAttribute("fillType").Equals("true"))
			{
				fillFatternType = FillFatternType.Color;
			}
			if (!xmlHelper.GetAttribute("ClearHeightValue").Equals("true"))
			{
				isText = false;
			}
			if (!xmlHelper.GetAttribute("Legent").Equals("true"))
			{
				islegent = false;
			}
		}

		private void CreateFillLegent(Dictionary<int, ElementId> fillDictionary)
		{
			Dictionary<int, ElementId> dictionary = (from o in fillDictionary
			orderby o.Key
			select o).ToDictionary((KeyValuePair<int, ElementId> o) => o.Key, (KeyValuePair<int, ElementId> p) => p.Value);
			Selection selection = this.m_uiDoc.Selection;
			if (this.m_LegentPosition == null)
			{
				try
				{
					XYZ legentPosition = selection.PickPoint("请输入图例插入点");
					this.m_LegentPosition = legentPosition;
				}
				catch (Exception)
				{
					return;
				}
			}
			XYZ xyz = this.m_LegentPosition;
			int num = this.m_doc.ActiveView.GetParameter(BuiltInParameter.VIEW_SCALE).AsInteger();
			double num2 = ClearHeightCheckFun.legentWidth * (double)num;
			double num3 = ClearHeightCheckFun.legentHigh * (double)num;
			Transaction transaction = new Transaction(this.m_doc, "createfillplan");
			transaction.Start();
			try
			{
				foreach (int key in dictionary.Keys)
				{
					List<XYZ> list = new List<XYZ>();
					list.Add(xyz);
					XYZ xyz2 = new XYZ(xyz.X + num2, xyz.Y, 0.0);
					list.Add(xyz2);
					XYZ item = new XYZ(xyz2.X, xyz2.Y - num3, 0.0);
					list.Add(item);
					XYZ xyz3 = new XYZ(xyz.X, xyz.Y - num3, 0.0);
					list.Add(xyz3);
					list.Add(xyz);
					List<CurveLoop> curveLoop = new List<CurveLoop>();
					curveLoop = this.GetListCurveLoop(list);
					ElementId filledRegionTypeId = dictionary[key];
					FilledRegion fillRegin = this.CreatefilledRegion(filledRegionTypeId, curveLoop, true);
					XYZ position = new XYZ(xyz2.X + num3 / 4.0, xyz2.Y - num3 / 2.0, 0.0);
					TextNote textNote = this.CreateTextNote(key.ToString(), position);
					this.SetFillReginParameters(fillRegin, textNote.Id, 2);
					xyz = new XYZ(xyz3.X, xyz3.Y - num3 / 4.0, 0.0);
				}
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		private List<CurveLoop> GetListCurveLoop(List<XYZ> listxyz)
		{
			List<Curve> list = new List<Curve>();
			for (int i = 0; i < listxyz.Count - 1; i++)
			{
				Line item = Line.CreateBound(listxyz[i], listxyz[i + 1]);
				list.Add(item);
			}
			List<CurveLoop> list2 = new List<CurveLoop>();
			CurveLoop item2 = CurveLoop.Create(list);
			list2.Add(item2);
			return list2;
		}

		private FilledRegion CreatefilledRegion(ElementId FilledRegionTypeId, List<CurveLoop> curveLoop, bool isVisible)
		{
			FilledRegion filledRegion = FilledRegion.Create(this.m_doc, FilledRegionTypeId, this.m_doc.ActiveView.Id, curveLoop);
			ElementSet elementSet = new ElementSet();
			elementSet.Insert(filledRegion);
			if (isVisible)
			{
				this.m_doc.ActiveView.UnHideYJKElements(elementSet);
			}
			else
			{
				this.m_doc.ActiveView.HideYJKElements(elementSet);
			}
			return filledRegion;
		}

		private void SetFillReginParameters(FilledRegion fillRegin, ElementId TextId, int nType)
		{
			Dictionary<string, ParameterType> dictionary = new Dictionary<string, ParameterType>();
            dictionary.Add("填充类型", (ParameterType)1);
			foreach (KeyValuePair<string, ParameterType> keyValuePair in dictionary)
			{
				if (fillRegin.GetParameter(keyValuePair.Key) == null)
				{
					SharedParameter.InsertSharedParameter(this.m_doc, BuiltInCategory.OST_DetailComponents, "图形图案填充", dictionary, true, true);
					break;
				}
			}
			if (nType == 0)
			{
				fillRegin.GetParameter("填充类型").Set("");
			}
			else if (nType == 1)
			{
				fillRegin.GetParameter("填充类型").Set("图形填充");
			}
			else if (nType == 2)
			{
				fillRegin.GetParameter("填充类型").Set("图例填充");
			}
			if (TextId != null)
			{
				Dictionary<string, ParameterType> dictionary2 = new Dictionary<string, ParameterType>();
                dictionary2.Add("对应文字ID", (ParameterType)1);
				foreach (KeyValuePair<string, ParameterType> keyValuePair2 in dictionary2)
				{
					if (fillRegin.GetParameter(keyValuePair2.Key) == null)
					{
						SharedParameter.InsertSharedParameter(this.m_doc, BuiltInCategory.OST_DetailComponents, "图形图案填充", dictionary2, true, true);
						break;
					}
				}
				fillRegin.GetParameter("对应文字ID").Set(TextId.IntegerValue.ToString());
			}
		}

		private TextNote CreateTextNote(string stext, XYZ position)
		{
			XYZ baseVec = new XYZ(1.0, 0.0, 0.0);
			XYZ upDirection = this.m_doc.ActiveView.UpDirection;
            TextAlignFlags textAlign = (TextAlignFlags)1088;
			return this.m_doc.GetTextNode(this.m_doc.ActiveView, position, baseVec, upDirection, ClearHeightCheckFun.legentTextLength, textAlign, stext);
		}

		private ElementId GetFillPatternId(List<FillPatternStruc> FillPatternList, double high, out bool isVisible)
		{
			isVisible = true;
			ElementId result = null;
			ElementId elementId = null;
			System.Drawing.Color color = default(System.Drawing.Color);
			for (int i = 0; i < FillPatternList.Count; i++)
			{
				if (i == 0 && high < FillPatternList[i].Lessthan * 1000.0)
				{
					elementId = FillPatternList[i].Id;
					isVisible = FillPatternList[i].Visible;
					color = FillPatternList[i].Color;
					break;
				}
				if (i == FillPatternList.Count - 1 && high > FillPatternList[i].Start * 1000.0)
				{
					elementId = FillPatternList[i].Id;
					isVisible = FillPatternList[i].Visible;
					color = FillPatternList[i].Color;
					break;
				}
				if (high > FillPatternList[i].Start * 1000.0 && high < FillPatternList[i].Lessthan * 1000.0)
				{
					elementId = FillPatternList[i].Id;
					isVisible = FillPatternList[i].Visible;
					color = FillPatternList[i].Color;
					break;
				}
			}
			FillPatternElement fillPatternElement = null;
			if (elementId != null)
			{
				fillPatternElement = (this.m_doc.GetElement(elementId) as FillPatternElement);
			}
			if (fillPatternElement == null)
			{
				IEnumerator<Element> enumerator = new FilteredElementCollector(this.m_doc).OfClass(typeof(FillPatternElement)).ToElements().GetEnumerator();
				{
					while (enumerator.MoveNext())
					{
						Element element = enumerator.Current;
						FillPatternElement fillPatternElement2 = element as FillPatternElement;
						if (fillPatternElement2 != null)
						{
							result = this.GetFilledRegionTypeId(fillPatternElement2, color);
							break;
						}
					}
					return result;
				}
			}
			result = this.GetFilledRegionTypeId(fillPatternElement, color);
			return result;
		}

		private ElementId GetFilledRegionTypeId(FillPatternElement fillPattern, System.Drawing.Color color)
		{
			IList<Element> list = new FilteredElementCollector(this.m_doc).OfClass(typeof(FilledRegionType)).ToElements();
			string text = string.Concat(new string[]
			{
				"HY_Region",
				this.GetFillPatternName(fillPattern.Name),
				color.A.ToString(),
				color.R.ToString(),
				color.G.ToString(),
				color.B.ToString()
			});
			foreach (Element element in list)
			{
				FilledRegionType filledRegionType = element as FilledRegionType;
				if (filledRegionType != null && filledRegionType.Name.CompareTo(text) == 0)
				{
					return filledRegionType.Id;
				}
			}
			if (list.Count < 1)
			{
				return null;
			}
			FilledRegionType filledRegionType2 = list[0] as FilledRegionType;
			ElementId result = null;
			Transaction transaction = new Transaction(this.m_doc, "createFilledRegionType");
			transaction.Start();
			try
			{
				FilledRegionType filledRegionType3 = filledRegionType2.Duplicate(text) as FilledRegionType;
				if (filledRegionType3 == null)
				{
					return null;
				}
				if (fillPattern != null)
				{
					RevitVersionFuncs.SetFillPatternId(ref filledRegionType3, fillPattern.Id);
				}
				try
				{
					RevitVersionFuncs.SetFillRegionColor(ref filledRegionType3, new Autodesk.Revit.DB.Color(color.R, color.G, color.B));
				}
				catch (Exception)
				{
				}
				result = filledRegionType3.Id;
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
				return null;
			}
			return result;
		}

		private string GetFillPatternName(string strFillPatternName)
		{
			string text = strFillPatternName;
			if (text.First<char>() == '<' && text.Last<char>() == '>')
			{
				text = text.TrimStart(new char[]
				{
					'<'
				}).TrimEnd(new char[]
				{
					'>'
				});
			}
			return text;
		}

		public void RefreshClearHeightPlan()
		{
			string name = this.m_doc.ActiveView.Name;
			if (-1 == name.IndexOf("净高分析图"))
			{
				YJKMessageBox.Show("请选择净高分析图");
				return;
			}
			List<ElementId> list = new List<ElementId>();
			IEnumerable<Element> enumerable = new FilteredElementCollector(this.m_doc).OfClass(typeof(FilledRegion)).ToElements();
			double num = double.MinValue;
			double num2 = double.MaxValue;
			foreach (Element element in enumerable)
			{
				if (!(element.OwnerViewId != this.m_doc.ActiveView.Id))
				{
					FilledRegion filledRegion = element as FilledRegion;
					ElementId elementId = null;
					string text = null;
					Parameter parameter = filledRegion.GetParameter("对应文字ID");
					if (parameter != null)
					{
						text = parameter.AsString();
					}
					if (text != null)
					{
						elementId = new ElementId(Convert.ToInt32(text));
					}
					Parameter parameter2 = filledRegion.GetParameter("填充类型");
					if (parameter2 != null)
					{
						string text2 = parameter2.AsString();
						if (text2 != null)
						{
							if (text2.Equals("图形填充"))
							{
								List<CurveLoop> item = new List<CurveLoop>();
								item = filledRegion.GetBoundaries().ToList<CurveLoop>();
								this.m_SelectedLoop.Add(item);
								if (null != elementId)
								{
									list.Add(elementId);
								}
								list.Add(filledRegion.Id);
							}
							else if (text2.Equals("图例填充"))
							{
								BoundingBoxXYZ boundingBoxXYZ = filledRegion.get_BoundingBox(this.m_doc.ActiveView);
								if (boundingBoxXYZ.Max.Y > num)
								{
									num = boundingBoxXYZ.Max.Y;
								}
								if (boundingBoxXYZ.Min.X < num2)
								{
									num2 = boundingBoxXYZ.Min.X;
								}
								if (null != elementId)
								{
									list.Add(elementId);
								}
								list.Add(filledRegion.Id);
							}
						}
					}
				}
			}
			if (this.m_SelectedLoop.Count < 1)
			{
				return;
			}
			this.deleteFillRegionItem(list);
			this.m_LegentPosition = new XYZ(num2, num, 0.0);
			this.CreateClearHeightPlan();
		}

		private void deleteFillRegionItem(List<ElementId> delIdList)
		{
			Transaction transaction = new Transaction(this.m_doc, "deleteFillRegionItem");
			transaction.Start();
			try
			{
				foreach (ElementId elementId in delIdList)
				{
					this.m_doc.Delete(elementId);
				}
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		public bool StartCheckClearHeight()
		{
			this.m_ClearHeightInLevels.Clear();
			bool result;
			if (this.m_isSelectedLevel)
			{
				result = this.CheckBySelectLevel();
			}
			else
			{
				result = this.CheckBySelectRegion(true);
			}
			return result;
		}

		private bool CheckBySelectRegion(bool isCheckHeight = true)
		{
			if (this.m_SelectedLoop.Count < 1)
			{
				return false;
			}
			Level genLevel = this.m_doc.ActiveView.GenLevel;
			if (genLevel == null)
			{
				return false;
			}
			List<CategoryItem> list = new List<CategoryItem>();
			list = SelectCategrayType.getCategoryItemListFromXML(isCheckHeight);
			if (list.Count < 1)
			{
				new List<Element>();
				SelectCategrayType selectCategrayType = new SelectCategrayType(this.getAllElements());
				selectCategrayType.initCategoryItemList();
				selectCategrayType.SaveToXmlFile(isCheckHeight);
				list = SelectCategrayType.getCategoryItemListFromXML(isCheckHeight);
			}
			if (list.Count < 1)
			{
				YJKMessageBox.Show("没有找到方案！");
				return false;
			}
			if (this._hWndRevit == null)
			{
				IntPtr mainWindowHandle = Process.GetCurrentProcess().MainWindowHandle;
                this._hWndRevit = new WindowHandle(mainWindowHandle);
			}
			ProgressBarForm progressBarForm = new ProgressBarForm(this.m_SelectedLoop.Count + 1, ProgressBarStyle.Blocks, true);
			progressBarForm.SetEscDisable(true);
			progressBarForm.Show(this._hWndRevit);
			progressBarForm.RefreshProgressBar();
			List<ClearHeightArea> list2 = new List<ClearHeightArea>();
			foreach (List<CurveLoop> list3 in this.m_SelectedLoop)
			{
				List<ElementAndClearHeight> elementHeightList = new List<ElementAndClearHeight>();
				elementHeightList = this.getAllElementClearHeight(list3, genLevel, list);
				ClearHeightArea clearHeightArea = new ClearHeightArea(list3);
				clearHeightArea.AddElementItems(elementHeightList);
				list2.Add(clearHeightArea);
				progressBarForm.RefreshProgressBar();
				if (progressBarForm.m_stopTag)
				{
					break;
				}
			}
			this.m_ClearHeightInLevels.Add(genLevel, list2);
			return true;
		}

		private bool CheckBySelectLevel()
		{
			if (this.m_SelectedlevelList.Count < 1)
			{
				return false;
			}
			List<CategoryItem> list = new List<CategoryItem>();
			list = SelectCategrayType.getCategoryItemListFromXML(true);
			if (list.Count < 1)
			{
				new List<Element>();
				SelectCategrayType selectCategrayType = new SelectCategrayType(this.getAllElements());
				selectCategrayType.initCategoryItemList();
				selectCategrayType.SaveToXmlFile(true);
				list = SelectCategrayType.getCategoryItemListFromXML(true);
			}
			if (list.Count < 1)
			{
				YJKMessageBox.Show("没有找到方案！");
				return false;
			}
			if (this._hWndRevit == null)
			{
				IntPtr mainWindowHandle = Process.GetCurrentProcess().MainWindowHandle;
                this._hWndRevit = new WindowHandle(mainWindowHandle);
			}
			foreach (Level level in this.m_SelectedlevelList)
			{
				Autodesk.Revit.DB.View activeView = level.Document.ActiveView;
				BoundingBoxXYZ boundingBox = this.getBoundingBox(level);
				if (boundingBox != null)
				{
					List<CurveLoop> list2 = new List<CurveLoop>();
					CurveLoop curveArray = this.getCurveArray(boundingBox);
					list2.Add(curveArray);
					List<ElementAndClearHeight> elementHeightList = new List<ElementAndClearHeight>();
					elementHeightList = this.getAllElementClearHeight(list2, level, list);
					List<ClearHeightArea> list3 = new List<ClearHeightArea>();
					ClearHeightArea clearHeightArea = new ClearHeightArea(list2);
					clearHeightArea.AddElementItems(elementHeightList);
					list3.Add(clearHeightArea);
					this.m_ClearHeightInLevels.Add(level, list3);
				}
			}
			return true;
		}

		private BoundingBoxXYZ getBoundingBox(Level level)
		{
			List<Floor> list = new List<Floor>();
			List<Wall> list2 = new List<Wall>();
			list = this.getFloorFromDoc(this.m_doc, level, false);
			list2 = this.getWallFromDoc(this.m_doc, level, false);
			foreach (Autodesk.Revit.DB.Document document in this.m_allLinkDocs)
			{
				if (document != null)
				{
					list.AddRange(this.getFloorFromDoc(document, level, true));
					list2.AddRange(this.getWallFromDoc(document, level, true));
				}
			}
			if (list.Count < 1 && list2.Count < 1)
			{
				return null;
			}
			double num = double.MinValue;
			double num2 = double.MinValue;
			double num3 = double.MaxValue;
			double num4 = double.MaxValue;
			foreach (Floor floor in list)
			{
				BoundingBoxXYZ boundingBoxXYZ = floor.get_BoundingBox(level.Document.ActiveView);
				if (boundingBoxXYZ != null)
				{
					if (boundingBoxXYZ.Max.X > num)
					{
						num = boundingBoxXYZ.Max.X;
					}
					if (boundingBoxXYZ.Max.Y > num2)
					{
						num2 = boundingBoxXYZ.Max.Y;
					}
					if (boundingBoxXYZ.Min.X < num3)
					{
						num3 = boundingBoxXYZ.Min.X;
					}
					if (boundingBoxXYZ.Min.Y < num4)
					{
						num4 = boundingBoxXYZ.Min.Y;
					}
				}
			}
			foreach (Wall wall in list2)
			{
				BoundingBoxXYZ boundingBoxXYZ2 = wall.get_BoundingBox(level.Document.ActiveView);
				if (boundingBoxXYZ2 != null)
				{
					if (boundingBoxXYZ2.Max.X > num)
					{
						num = boundingBoxXYZ2.Max.X;
					}
					if (boundingBoxXYZ2.Max.Y > num2)
					{
						num2 = boundingBoxXYZ2.Max.Y;
					}
					if (boundingBoxXYZ2.Min.X < num3)
					{
						num3 = boundingBoxXYZ2.Min.X;
					}
					if (boundingBoxXYZ2.Min.Y < num4)
					{
						num4 = boundingBoxXYZ2.Min.Y;
					}
				}
			}
			return new BoundingBoxXYZ
			{
				Max = new XYZ(num, num2, 0.0),
				Min = new XYZ(num3, num4, 0.0)
			};
		}

		private List<Floor> getFloorFromDoc(Autodesk.Revit.DB.Document doc, Level level, bool isLinkDoc)
		{
			List<Floor> list = new List<Floor>();
			if (isLinkDoc)
			{
				foreach (Element element in ((IEnumerable<Element>)new FilteredElementCollector(doc).OfClass(typeof(Level)).ToElements().ToList<Element>()))
				{
					Level level2 = (Level)element;
					if (Math.Abs(level.Elevation - level2.Elevation) < ClearHeightCheckFun.tol)
					{
						break;
					}
				}
				return list;
			}
			foreach (Element element2 in ((IEnumerable<Element>)new FilteredElementCollector(doc).OfClass(typeof(Floor)).ToElements().ToList<Element>()))
			{
				Floor floor = element2 as Floor;
				if (floor.LevelId == level.Id)
				{
					list.Add(floor);
				}
			}
			return list;
		}

		private List<Wall> getWallFromDoc(Autodesk.Revit.DB.Document doc, Level level, bool isLinkDoc)
		{
			List<Wall> list = new List<Wall>();
			if (isLinkDoc)
			{
				foreach (Element element in ((IEnumerable<Element>)new FilteredElementCollector(doc).OfClass(typeof(Level)).ToElements().ToList<Element>()))
				{
					Level level2 = (Level)element;
					if (Math.Abs(level.Elevation - level2.Elevation) < ClearHeightCheckFun.tol)
					{
						break;
					}
				}
				return list;
			}
			foreach (Element element2 in ((IEnumerable<Element>)new FilteredElementCollector(doc).OfClass(typeof(Wall)).ToElements().ToList<Element>()))
			{
				Wall wall = element2 as Wall;
				if (wall.LevelId == level.Id)
				{
					list.Add(wall);
				}
			}
			return list;
		}

		private void getCheckFloorType()
		{
			List<FloorType> list = new List<FloorType>();
			list = this.GetFloorsTypeFromDoc(this.m_doc);
			foreach (FloorType floorType in list)
			{
				FloorType floorType2 = floorType as FloorType;
				if (floorType2.Name.Equals("checkFloor"))
				{
					this.m_CheckfloorType = floorType2;
					return;
				}
			}
			if (this.m_CheckfloorType == null)
			{
				if (list.Count < 1)
				{
					foreach (Autodesk.Revit.DB.Document document in this.m_allLinkDocs)
					{
						if (document != null)
						{
							List<FloorType> collection = new List<FloorType>();
							collection = this.GetFloorsTypeFromDoc(document);
							list.AddRange(collection);
						}
					}
				}
				FloorType floorType3 = list[0];
				Document document2 = floorType3.Document;
				FloorType floorType4 = null;
				if (document2.Equals(this.m_doc))
				{
					floorType4 = floorType3;
				}
				else
				{
					Transaction transaction = new Transaction(this.m_doc, "copyFloorType");
					transaction.Start();
					IEnumerable<ElementId> enumerable = ElementTransformUtils.CopyElements(document2, new List<ElementId>
					{
						floorType3.Id
					}, this.m_doc, Transform.Identity, new CopyPasteOptions());
					transaction.Commit();
					foreach (ElementId elementId in enumerable)
					{
						floorType4 = (this.m_doc.GetElement(elementId) as FloorType);
					}
				}
				Transaction transaction2 = new Transaction(this.m_doc, "CreatecopyFloor");
				transaction2.Start();
				this.m_CheckfloorType = (floorType4.Duplicate("checkFloor") as FloorType);
				transaction2.Commit();
			}
		}

		private List<FloorType> GetFloorsTypeFromDoc(Autodesk.Revit.DB.Document doc)
		{
			List<FloorType> list = new List<FloorType>();
			foreach (Element element in ((IEnumerable<Element>)new FilteredElementCollector(doc).OfClass(typeof(FloorType)).ToElements().ToList<Element>()))
			{
				FloorType item = element as FloorType;
				list.Add(item);
			}
			return list;
		}

		private CurveLoop getCurveArray(BoundingBoxXYZ boundBox)
		{
			List<Curve> list = new List<Curve>();
			XYZ max = boundBox.Max;
			XYZ min = boundBox.Min;
			List<XYZ> list2 = new List<XYZ>();
			XYZ item = new XYZ(min.X, min.Y, 0.0);
			list2.Add(item);
			XYZ item2 = new XYZ(max.X, min.Y, 0.0);
			list2.Add(item2);
			XYZ item3 = new XYZ(max.X, max.Y, 0.0);
			list2.Add(item3);
			XYZ item4 = new XYZ(min.X, max.Y, 0.0);
			list2.Add(item4);
			list2.Add(item);
			for (int i = 0; i < list2.Count - 1; i++)
			{
				Line item5 = Line.CreateBound(list2[i], list2[i + 1]);
				list.Add(item5);
			}
			return CurveLoop.Create(list);
		}

		private List<ElementAndClearHeight> getAllElementClearHeight(List<CurveLoop> curveLoopList, Level level, List<CategoryItem> categoryList)
		{
			List<ElementAndClearHeight> result = new List<ElementAndClearHeight>();
			List<CurveLoop> list = new List<CurveLoop>();
			if (this.m_isSelectedLevel)
			{
				using (List<CurveLoop>.Enumerator enumerator = curveLoopList.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						CurveLoop curveLoop = enumerator.Current;
						CurveLoop curveLoop2 = new CurveLoop();
						foreach (Curve curve in curveLoop)
						{
							Transform transform = Transform.CreateTranslation(new XYZ(0.0, 0.0, level.Elevation) - XYZ.Zero);
							Curve curve2 = curve.CreateTransformed(transform);
							curveLoop2.Append(curve2);
						}
						list.Add(curveLoop2);
					}
					goto IL_C0;
				}
			}
			list.AddRange(curveLoopList);
			IL_C0:
			Transaction transaction = new Transaction(this.m_doc, "CreateSolid");
			transaction.Start();
			try
			{
				double num = this.m_SpaceHeight / 304.8;
				Solid solid = GeometryCreationUtilities.CreateExtrusionGeometry(list, XYZ.BasisZ, num);
				if (null == solid)
				{
					transaction.RollBack();
					return result;
				}
				this.m_doc.Regenerate();
				double num2 = 0.0;
				if (!this.m_isSelectedFloor)
				{
					num2 = level.Elevation;
					num2 = this.feetToMM(num2);
				}
				else
				{
					IEnumerator<Curve> enumerator2 = list[0].GetEnumerator();
					{
						if (enumerator2.MoveNext())
						{
							num2 = enumerator2.Current.GetEndPoint(0).Z;
							num2 = this.feetToMM(num2);
						}
					}
				}
				result = this.getInsectionElement(solid, num2, categoryList);
				transaction.RollBack();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
			return result;
		}

		private Floor CreateCheckFloor(CurveArray curveList, Level level, double clearHeight, double offset)
		{
			double num = (clearHeight + offset) / 304.8;
            MaterialFunctionAssignment materialFunctionAssignment = (MaterialFunctionAssignment)1;
			double num2 = num;
			ElementId invalidElementId = ElementId.InvalidElementId;
			CompoundStructure compoundStructure = CompoundStructure.CreateSingleLayerCompoundStructure(materialFunctionAssignment, num2, invalidElementId);
            compoundStructure.EndCap = (EndCapCondition)3;
			this.m_CheckfloorType.SetCompoundStructure(compoundStructure);
			Floor floor = this.m_doc.Create.NewFloor(curveList, this.m_CheckfloorType, level, false);
			floor.GetParameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM).Set(num);
			return floor;
		}

		private List<ElementAndClearHeight> getInsectionElement(Solid floorSolid, double floorHeight, List<CategoryItem> categoryList)
		{
			List<ElementAndClearHeight> list = new List<ElementAndClearHeight>();
			List<Element> list2 = new List<Element>();
			list2 = this.getInsectionElementByDoc(this.m_doc, floorSolid);
			foreach (Autodesk.Revit.DB.Document document in this.m_allLinkDocs)
			{
				if (document != null)
				{
					List<Element> collection = new List<Element>();
					collection = this.getInsectionElementByDoc(document, floorSolid);
					list2.AddRange(collection);
				}
			}
			foreach (Element element in list2)
			{
				double num;
				BuiltInCategory elementHeight = this.getElementHeight(element, floorSolid, categoryList, out num);
                if (-1 != (int)elementHeight)
				{
					double num2 = num - floorHeight;
					if (num2 >= ClearHeightCheckFun.tolMax)
					{
						bool flag = false;
						foreach (ElementAndClearHeight elementAndClearHeight in list)
						{
							if (elementHeight == elementAndClearHeight.getElementCategory() && Math.Abs(num2 - elementAndClearHeight.getClearHeight()) < ClearHeightCheckFun.tol)
							{
								flag = true;
								elementAndClearHeight.addElement(element);
								break;
							}
						}
						if (!flag)
						{
							ElementAndClearHeight elementAndClearHeight2 = new ElementAndClearHeight(num2, elementHeight);
							elementAndClearHeight2.addElement(element);
							list.Add(elementAndClearHeight2);
						}
					}
				}
			}
			return list;
		}

		private List<Element> getInsectionElementByDoc(Autodesk.Revit.DB.Document doc, Solid solid)
		{
			return ElementSearchMethod.GetInsectionElementByDoc(doc, solid);
		}

		public Dictionary<Level, List<ClearHeightArea>> getClearHeightInLevel()
		{
			return this.m_ClearHeightInLevels;
		}

		private BuiltInCategory getElementHeight(Element element, Solid floorSolid, List<CategoryItem> categoryList, out double height)
		{
			BuiltInCategory builtInCategory = (BuiltInCategory)(-1);
			height = 0.0;
			Category category = element.Category;
			Document document = element.Document;
			Autodesk.Revit.DB.ElementType eType = document.GetElement(element.GetTypeId()) as Autodesk.Revit.DB.ElementType;
			int num = categoryList.FindIndex((CategoryItem value) => value.CategoryId() == category.Id.IntegerValue);
			if (-1 != num)
			{
				CategoryItem categoryItem = categoryList[num];
				List<ObjectTypeItem> list = new List<ObjectTypeItem>();
				list = categoryItem.ObjectTypeItemList;
				int num2 = list.FindIndex((ObjectTypeItem value) => value.getTypeName().Equals(eType.Name));
				if (-1 != num2 && list[num2].Selected)
				{
					if (element is MEPCurve)
					{
						Curve curve = (element.Location as LocationCurve).Curve;
						XYZ xyz = curve.GetEndPoint(1) - curve.GetEndPoint(0);
						xyz.Normalize();
						if (xyz.IsAlmostEqualTo(XYZ.BasisZ) || xyz.IsAlmostEqualTo(-XYZ.BasisZ))
						{
							return (BuiltInCategory)(-1);
						}
					}
                    builtInCategory = (BuiltInCategory)element.Category.Id.IntegerValue;
				}
			}
            if ((int)builtInCategory == -1)
			{
				return builtInCategory;
			}
			if (!this.CalculateElementHeight(element, floorSolid, out height))
			{
				return (BuiltInCategory)(-1);
			}
			return builtInCategory;
		}

		private bool CalculateElementHeight(Element element, Solid floorSolid, out double height)
		{
			height = 0.0;
			List<Solid> list = new List<Solid>();
			list = this.GetElementSolids(element);
			if (list.Count < 1)
			{
				return false;
			}
			double num = double.MaxValue;
			try
			{
				foreach (Solid solid in list)
				{
					if (!(solid == null))
					{
						Solid solid2 = BooleanOperationsUtils.ExecuteBooleanOperation(floorSolid, solid, (Autodesk.Revit.DB.BooleanOperationsType)2);
						if (!(solid2 == null))
						{
							foreach (object obj in solid2.Faces)
							{
								Face face = (Face)obj;
								if (!(null == face))
								{
									Mesh mesh = face.Triangulate(0.5);
									for (int i = 0; i < mesh.NumTriangles; i++)
									{
										new List<XYZ>();
										MeshTriangle meshTriangle = mesh.get_Triangle(i);
										for (int j = 0; j < 3; j++)
										{
											XYZ xyz = meshTriangle.get_Vertex(j);
											if (xyz.Z < num)
											{
												num = xyz.Z;
											}
										}
									}
								}
							}
						}
					}
				}
			}
			catch (Exception)
			{
			}
			height = this.feetToMM(num);
			return true;
		}

		public List<Level> GetCurDocLevels()
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
			filteredElementCollector.WherePasses(new ElementClassFilter(typeof(Level)));
			foreach (Element element in filteredElementCollector.ToElements())
			{
				Level level = element as Level;
				bool flag = false;
				for (int i = 0; i < this.m_levelList.Count; i++)
				{
					Level level2 = this.m_levelList[i];
					if (level.Elevation < level2.Elevation)
					{
						this.m_levelList.Insert(i, level);
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					this.m_levelList.Add(level);
				}
			}
			return this.m_levelList;
		}

		public void setSelectFloor(bool isSelectFloor = false)
		{
			this.m_isSelectedFloor = isSelectFloor;
		}

		public void setSelectedLevelList(List<Level> SelectedlevelList)
		{
			this.m_SelectedlevelList = SelectedlevelList;
		}

		public void setSelectType(bool isSelectLevel = true)
		{
			this.m_isSelectedLevel = isSelectLevel;
		}

		public void setSpaceHeight(double dSpaceHeight)
		{
			this.m_SpaceHeight = dSpaceHeight * 1000.0;
		}

		public void setUserSelectedArea(List<List<CurveLoop>> SelectedLoop)
		{
			this.m_SelectedLoop = SelectedLoop;
		}

		private double feetToMM(double val)
		{
			return val * 304.8;
		}

		private static List<Document> GetLinkDocs(Autodesk.Revit.DB.Document doc)
		{
			List<Document> list = new List<Document>();
			try
			{
				foreach (RevitLinkInstance revitLinkInstance in ((IEnumerable<RevitLinkInstance>)new FilteredElementCollector(doc).OfClass(typeof(RevitLinkInstance)).Cast<RevitLinkInstance>().ToList<RevitLinkInstance>()))
				{
					list.Add(revitLinkInstance.GetLinkDocument());
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			return list;
		}

		private List<Solid> GetElementSolids(Element element)
		{
			Options options = this.m_UiApp.Application.Create.NewGeometryOptions();
			options.DetailLevel = (ViewDetailLevel)3;
			options.IncludeNonVisibleObjects = true;
			GeometryElement geometryElement;
			if (element.GetType() == typeof(FamilyInstance))
			{
				FamilyInstance familyInstance = element as FamilyInstance;
				geometryElement = familyInstance.GetOriginalGeometry(options);
				geometryElement = geometryElement.GetTransformed(familyInstance.GetTransform());
			}
			else
			{
				geometryElement = element.get_Geometry(options);
			}
			List<Solid> list = new List<Solid>();
			if (null == geometryElement)
			{
				return list;
			}
			foreach (GeometryObject geometryObject in geometryElement)
			{
				if (!(geometryObject.GetType() != typeof(Solid)))
				{
					Solid solid = geometryObject as Solid;
					if (solid != null && solid.Volume - 0.001 >= -0.0001)
					{
						list.Add(solid);
					}
				}
			}
			return list;
		}

		private UIApplication m_UiApp;

		public UIDocument m_uiDoc;

		public Document m_doc;

        private WindowHandle _hWndRevit;

		private List<Level> m_levelList = new List<Level>();

		private List<Document> m_allLinkDocs = new List<Document>();

		private FloorType m_CheckfloorType;

		private static double tol = 1E-05;

		private static double tolMax = 1500.0;

		private List<Level> m_SelectedlevelList = new List<Level>();

		private List<List<CurveLoop>> m_SelectedLoop = new List<List<CurveLoop>>();

		private Element m_ZoomElement;

		private double m_SpaceHeight = 2100.0;

		private bool m_isSelectedLevel = true;

		private bool m_isSelectedFloor;

		private XYZ m_LegentPosition;

		private static double legentHigh = 0.02624;

		private static double legentWidth = 0.0656;

		private static double legentTextLength = 0.1;

		private Dictionary<Level, List<ClearHeightArea>> m_ClearHeightInLevels = new Dictionary<Level, List<ClearHeightArea>>();
	}
}
